#include "PanoramicDealReceiver.h"

#include <bondlib/BondDeal/BondDealTermRange.h>
#include <bondlib/BondDeal/PanoramicBondDealContainer.h>
#include <msgcenter/PanoramicDealProcess.h>
#include <qbkernel/include/qb_base.h>
#include <qbprotocol/include/MessageParserTool.h>
#include <qbprotocol/include/SSMsgStruct.h>
#include <qbprotocol/include/rdProto.h>
#include <qbtools/message/MessagePoster.h>
#include <uam/UserAccountManager.h>

using namespace qb;

PanoramicDealReceiver& PanoramicDealReceiver::instance() {
  static PanoramicDealReceiver s_pd;
  return s_pd;
}

void PanoramicDealReceiver::requestPanoramicDeal(bool bForce) {
  if (!bForce && CPanoramicBondDealContainer::instance().GetReqData()) return;

  bool bNewDealSource =
      strcmp(SSUserAccountManager::instance().GetGlobleVariabl(
                 SSUserAccountManager::UseNewDealSource),
             "1") == 0;

  CPanoramicBondDealContainer::instance().Clear();
  CPanoramicBondDealContainer::instance().SetReqData();

  xQBPanoramicMarketStreamDealReq req;
  req.m_IndexFrom = 0;
  req.m_IndexTo = -1;

  qb::SSRequestMsg msg;
  memset(&msg, 0, sizeof(qb::SSRequestMsg));

  msg.m_FuncID = bNewDealSource ? E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_PUSH_V3
                                : E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_PUSH;
  PushMsgInfo pmi(msg.m_FuncID, "", nullptr);
  registPush(pmi, &msg, qbmsg::panoramic::EncodeFunc);

  msg.m_pRequest = (void*)&req;
  msg.m_FuncID = bNewDealSource ? E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_REQ_V3
                                : E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_REQ_V2;
  MessagePoster poster(&msg, qbmsg::panoramic::EncodeFunc);
  poster.send(this);
}

void PanoramicDealReceiver::requestTermRange() {
  CBondDealTermRange::emBondType type = CBondDealTermRange::bondType_Interest;
  CBondDealTermRange& tRange = CBondDealTermRange::instance();
  if (tRange.IsInited()) return;

  SSUserAccountManager& uam = SSUserAccountManager::instance();

  xQBBondDealTermRgReq req;
  FIELDCOPY(req.m_UserId, uam.GetUserInfo().m_UserId);
  FIELDCOPY(req.m_UserAccount, uam.GetUserInfo().m_UserAccount);
  for (auto itRange : std::vector<int>{CBondDealTermRange::bondType_Interest,
                                       CBondDealTermRange::bondType_Credit,
                                       CBondDealTermRange::bondType_NCDPrimary,
                                       CBondDealTermRange::bondType_NCD}) {
    sBondDealTermList unitMatrix;

    unitMatrix.m_nRate = (int)itRange;
    int nColCount = 0;
    if (itRange == CBondDealTermRange::bondType_Interest)
      nColCount = CBondDealTermRange::termRg_Interest;
    else if (itRange == CBondDealTermRange::bondType_Credit)
      nColCount = CBondDealTermRange::termRg_Credit;
    else if (itRange == CBondDealTermRange::bondType_NCDPrimary)
      nColCount = CBondDealTermRange::termRg_NCDPrimary;
    else if (itRange == CBondDealTermRange::bondType_NCD)
      nColCount = CBondDealTermRange::termRg_NCD;
    for (int nL = 1; nL < nColCount; nL++) {
      sBondDealTermRgUnit unitTerm;
      if (itRange == CBondDealTermRange::bondType_Interest) {
        FIELDCOPY(unitTerm.m_term, strInterestRange[nL].c_str());
        unitTerm.m_nCol = nL;
      } else if (itRange == CBondDealTermRange::bondType_Credit) {
        FIELDCOPY(unitTerm.m_term, strCreditRange[nL].c_str());
        unitTerm.m_nCol = nL;
      } else if (itRange == CBondDealTermRange::bondType_NCDPrimary) {
        FIELDCOPY(unitTerm.m_term, strNCDPrimaryRange[nL].c_str());
        unitTerm.m_nCol = nL;
      } else if (itRange == CBondDealTermRange::bondType_NCD) {
        FIELDCOPY(unitTerm.m_term, strNCDRange[nL].c_str());
        unitTerm.m_nCol = nL;
      }
      if (!tRange.GetRange(
              unitTerm, static_cast<CBondDealTermRange::emBondType>(itRange))) {
        tRange.InitDefaultRange(
            unitTerm, static_cast<CBondDealTermRange::emBondType>(itRange));
        unitMatrix.m_listTerm.push_back(unitTerm);
      }
    }
    req.m_matrixTerm.push_back(unitMatrix);
  }

  {
    // 为测试暂时先放入默认数据
    xQBBondDealTermRgAck ack;
    ack.m_matrixTerm = req.m_matrixTerm;
    tRange.UpdateRange(&ack, true);
  }

  if (!req.m_matrixTerm.empty()) {
    qb::SSRequestMsg msg;
    memset(&msg, 0, sizeof(qb::SSRequestMsg));
    msg.m_pRequest = (void*)&req;
    msg.m_FuncID = E_FID_QB_DEAL_TERM_RANGE_OVERALL_REQ;
    MessagePoster poster(&msg, qbmsg::panoramic::EncodeFunc);
    poster.send(this);
  }
}

void PanoramicDealReceiver::onDataArrived(const qb::SSAckMsg& msg) {
  int funcId = msg.m_FuncID;
  switch (funcId) {
    case E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_REQ_V2:
    case E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_PUSH:
    case E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_REQ_V3:
    case E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_PUSH_V3: {
      xQBPanoramicMarketStreamDealAck* data =
          (xQBPanoramicMarketStreamDealAck*)msg.m_pRet;
      if (!data) break;
      CPanoramicBondDealContainer::instance().UpdateBondDeal(data);
      QList<xQBPanoramicMarketStreamUnit> lst;
      if (funcId == E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_PUSH ||
          funcId == E_FID_QB_PANORAMIC_MARKET_STREAM_DEAL_PUSH_V3) {
        for (std::list<xQBPanoramicMarketStreamUnit>::const_iterator itor =
                 data->m_List.begin();
             itor != data->m_List.end(); itor++) {
          lst.push_back(*itor);
        }
        dealMarketPush(funcId, lst);
      } else {
        if (msg.m_IsReceving == 0) dealMarketArrived();
      }
      break;
    }
    case E_FID_QB_DEAL_TERM_RANGE_OVERALL_REQ:
    case E_FID_QB_DEAL_TERM_RANGE_OVERALL_MODIFY: {
      xQBBondDealTermRgAck* pdata = (xQBBondDealTermRgAck*)msg.m_pRet;
      if (!pdata) break;
      CBondDealTermRange::instance().UpdateRange(pdata, false);
      if (funcId == E_FID_QB_DEAL_TERM_RANGE_OVERALL_REQ &&
          msg.m_IsReceving == 0)
        termRangeArrived();
      break;
    }
    default:
      break;
  }
}

PanoramicDealReceiver::PanoramicDealReceiver() {
  qbmsg::panoramic::InitDecodeFuncs();
  qRegisterMetaType<QList<xQBPanoramicMarketStreamUnit> >(
      "QList<xQBPanoramicMarketStreamUnit>");
}
